from copy import *
from sets import *
from yant import *

def loadGrammar(fname):
    f = open(fname)

    n = {}
    t = {}

    rules = []
    code = []

    for l in f:
        l = l.strip()
        if not l:
            continue
        if l.startswith('$'):
            code.append(l[1:])
            continue
        if l.startswith('#'):
            continue
        if l.endswith(';'):
            l = l[:-1]
        try:
            left, right, action = map(lambda x : x.strip(), l.split(':'))
        except:
            raise RuntimeError('Error parsing grammar line: %s' % l )
        right = map(lambda x : x.strip(), right.split())
        rules.append( (left, right, action) )

    for left, right, action in rules:
        assert(not left in t.keys())
        if not left in n.keys():
            n[left] = NTSymbol(left)

    for left, right, action in rules:
        for r in right:
            if not r in n.keys():
                t[r] = TSymbol(r)

    all = copy(t)
    all.update(n)

    g = Grammar()
    g.addCode(code)
    for left, right, action in rules:

        leftsym = n[left]
        rightsyms = map(lambda x: all[x], right)

        g.addProduction( Production(leftsym, rightsyms, action) )

    g.build(n[rules[0][0]])

    return g
